/*******************************************************************************
 * Copyright (c) 2006 CEA List.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     CEA List - initial API and implementation
 *******************************************************************************/
package com.cea.papyrus.diagram.usecase;

import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPartFactory;
import org.eclipse.uml2.uml.Abstraction;
import org.eclipse.uml2.uml.Actor;
import org.eclipse.uml2.uml.Association;
import org.eclipse.uml2.uml.Comment;
import org.eclipse.uml2.uml.Constraint;
import org.eclipse.uml2.uml.Dependency;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.ElementImport;
import org.eclipse.uml2.uml.Extend;
import org.eclipse.uml2.uml.ExtensionPoint;
import org.eclipse.uml2.uml.Generalization;
import org.eclipse.uml2.uml.Include;
import org.eclipse.uml2.uml.Package;
import org.eclipse.uml2.uml.PackageImport;
import org.eclipse.uml2.uml.Realization;
import org.eclipse.uml2.uml.Usage;
import org.eclipse.uml2.uml.UseCase;

import com.cea.papyrus.core.editor.EditpartFactoryBase;
import com.cea.papyrus.core.editor.ModelManager;
import com.cea.papyrus.core.editpart.AnchorEditPart;
import com.cea.papyrus.core.editpart.GraphEdgeEditPart;
import com.cea.papyrus.core.editpart.GraphNodeWithSemanticEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.AbstractionEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.AssociationEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.CommentEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.DependencyEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.GeneralizationEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.PackageEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.PackageImportEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.RealizationEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.UsageEditPart;
import com.cea.papyrus.diagram.composite.editpart.ClassEditPart;
import com.cea.papyrus.diagram.usecase.editpart.ActorEditPart;
import com.cea.papyrus.diagram.usecase.editpart.ActorNameDisplayEditPart;
import com.cea.papyrus.diagram.usecase.editpart.ConstraintEditPart;
import com.cea.papyrus.diagram.usecase.editpart.ExtendEditPart;
import com.cea.papyrus.diagram.usecase.editpart.ExtensionPointEditPart;
import com.cea.papyrus.diagram.usecase.editpart.IncludeEditPart;
import com.cea.papyrus.diagram.usecase.editpart.UseCaseDiagramEditPart;
import com.cea.papyrus.diagram.usecase.editpart.UseCaseEditPart;
import com.cea.papyrus.diagram.usecase.editpart.UseCaseNameDisplayEditPart;
import com.cea.papyrus.diagraminterchange2.di2.Diagram;
import com.cea.papyrus.diagraminterchange2.di2.GraphEdge;
import com.cea.papyrus.diagraminterchange2.di2.GraphElement;
import com.cea.papyrus.diagraminterchange2.di2.GraphNode;
import com.cea.papyrus.diagraminterchange2.di2.Uml1SemanticModelBridge;

/**
 * Manages creation of controllers for usecase diagram elements.
 */
public class UseCaseDiagramGraphicalEditPartsFactory extends EditpartFactoryBase implements EditPartFactory {
	
	/** The model manager associated to this editor */
	protected ModelManager modelManager;

	/**
	 * Creates a new factory for the edit parts for the use case diagram editor
	 * @param modelManager the model manager associated to the editor
	 */
	public UseCaseDiagramGraphicalEditPartsFactory(ModelManager modelManager) {
		this.modelManager = modelManager;
	}

	/**
	 * Creates the edit part.
	 * 
	 * @param obj the obj
	 * @param context the context
	 * 
	 * @return the edit part
	 */
	public EditPart createEditPart(EditPart context, Object obj) {
		//new mechanism
		EditPart result= getEditPartFromProperty(context, obj,modelManager);
		if (result!=null){
			return result;
		}
		// to identify the good editpart we need the nature of the object
		// graphEdge or graphNode and
		// uml Elment connected
		// case of a diagram
		if (obj instanceof Diagram) {
			return new UseCaseDiagramEditPart((Diagram) obj, modelManager);
		} else if (obj instanceof GraphNode) {
			if (((GraphNode) obj).getSemanticParent() != null && ((Uml1SemanticModelBridge)((GraphElement)((GraphNode) obj).getSemanticParent()).getSemanticModel()).getElement() instanceof UseCase) {
				Element umlSemanticParent= ((Uml1SemanticModelBridge)((GraphElement)((GraphNode) obj).getSemanticParent()).getSemanticModel()).getElement();
				((GraphNode) obj).setSemanticModel(null);
				return new UseCaseNameDisplayEditPart((GraphNode) obj,umlSemanticParent, modelManager);
			}
			if (((GraphNode) obj).getSemanticParent() != null && ((Uml1SemanticModelBridge)((GraphElement)((GraphNode) obj).getSemanticParent()).getSemanticModel()).getElement() instanceof Actor) {
				Element umlSemanticParent= ((Uml1SemanticModelBridge)((GraphElement)((GraphNode) obj).getSemanticParent()).getSemanticModel()).getElement();
				((GraphNode) obj).setSemanticModel(null);
				return new ActorNameDisplayEditPart((GraphNode) obj,umlSemanticParent, modelManager);
			}
			if (((Uml1SemanticModelBridge) ((GraphNode) obj).getSemanticModel()) == null) {
				return new AnchorEditPart((GraphNode) obj, modelManager);
			}
			if ((((Uml1SemanticModelBridge) ((GraphNode) obj)
					.getSemanticModel()).getElement()) == null) {
				return new GraphNodeWithSemanticEditPart((GraphNode) obj,
						modelManager);
			}
			Element elt = ((Uml1SemanticModelBridge) ((GraphNode) obj)
					.getSemanticModel()).getElement();
			return searchEditPart((GraphNode) obj, elt);
		}

		// case of a graphEdge
		else if (obj instanceof GraphEdge) {
			if (((Uml1SemanticModelBridge) ((GraphEdge) obj).getSemanticModel()) != null) {
				if (((Uml1SemanticModelBridge) ((GraphEdge) obj)
						.getSemanticModel()).getElement() instanceof PackageImport) {
					return new PackageImportEditPart((GraphEdge) obj, modelManager);
				} else if (((Uml1SemanticModelBridge) ((GraphEdge) obj)
						.getSemanticModel()).getElement() instanceof Extend) {
					return new ExtendEditPart((GraphEdge) obj, modelManager);
				} else if (((Uml1SemanticModelBridge) ((GraphEdge) obj)
						.getSemanticModel()).getElement() instanceof Include) {
					return new IncludeEditPart((GraphEdge) obj, modelManager);
				} else if (((Uml1SemanticModelBridge)((GraphEdge)obj).getSemanticModel()).getElement() instanceof Usage){
					return new UsageEditPart((GraphEdge)obj,modelManager);
				} else if (((Uml1SemanticModelBridge)((GraphEdge)obj).getSemanticModel()).getElement() instanceof Realization){
					return new RealizationEditPart((GraphEdge)obj,modelManager);
				} else if (((Uml1SemanticModelBridge)((GraphEdge)obj).getSemanticModel()).getElement() instanceof Abstraction){
					return new AbstractionEditPart((GraphEdge)obj,modelManager);
				} else if (((Uml1SemanticModelBridge)((GraphEdge)obj).getSemanticModel()).getElement() instanceof Dependency){
					return new DependencyEditPart((GraphEdge)obj,modelManager);
				} else if (((Uml1SemanticModelBridge) ((GraphEdge) obj)
						.getSemanticModel()).getElement() instanceof Generalization) {
					return new GeneralizationEditPart((GraphEdge) obj, modelManager);
				} else if (((Uml1SemanticModelBridge) ((GraphEdge) obj)
						.getSemanticModel()).getElement() instanceof Association) {
					return new AssociationEditPart((GraphEdge) obj, modelManager);
				}

			} else {
				GraphEdge ge = (GraphEdge) obj;
				return new GraphEdgeEditPart(ge, modelManager);
			}
		}
		return null;
	}

	/**
	 * Create the good Edit part from the the GraphNode and the Element.
	 * 
	 * @param graphNode the graph node
	 * @param elt the elt
	 * 
	 * @return the edit part
	 */
	public EditPart searchEditPart(GraphNode graphNode, Element elt) {
		//Type elements
		if (elt instanceof ElementImport){
			// in the case of element Import, we need to recall this method
			return searchEditPart(graphNode, ((ElementImport)elt).getImportedElement());
		}
		// Constraint
		if (elt instanceof Constraint) {
			return new ConstraintEditPart(graphNode, modelManager);
		}
		// ExtensionPoint
		if (elt instanceof ExtensionPoint) {
			return new ExtensionPointEditPart(graphNode, modelManager);
		}
		// Actor
		if (elt instanceof Actor) {
			return new ActorEditPart(graphNode, modelManager);
		}
		// UseCase
		if (elt instanceof UseCase) {
			return new UseCaseEditPart(graphNode, modelManager);
		}
		// Package
		if (elt instanceof Package) {
			return new PackageEditPart(graphNode, modelManager);
		}
		// Comment
		if (elt instanceof Comment) {
			return new CommentEditPart(graphNode, modelManager);
		}
		// Class
		if (elt instanceof org.eclipse.uml2.uml.Class) {
			return new ClassEditPart(graphNode, modelManager);
		}
		
		return null;
	}
}